Merge main into alpha/v2.0.0#325
Merged
heyitsaamir merged 13 commits intoalpha/v2.0.0from Mar 25, 2026
Merged
Conversation
It’s time we start formalizing our relationship with Claude :). This PR initializes a simple .claude.md with some common rules that claude tends to get wrong often. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
before, when you do `Ctrl-C` after running the sample via the terminal, it would throw a giant trace: <img width="1469" height="883" alt="image" src="https://github.com/user-attachments/assets/4760dc08-7534-4301-9a95-61d60ff6d7a1" /> now, with this update: <img width="791" height="369" alt="image" src="https://github.com/user-attachments/assets/3c11b786-1ba0-46b8-a29a-1e5281a05255" /> --------- Co-authored-by: lilydu <lilydu+odspmdb@microsoft.com>
This is a python adaptation of microsoft/teams.ts#424. Separate activity sending from HTTP transport layer The previous architecture tightly coupled HTTP transport concerns with activity sending logic: **Previous Architecture:** ``` HttpPlugin (transport) → implements ISender (sending) → has send() method (creates new Client per call) → has createStream() method → knows about Activity protocol details ActivityContext → depends on ISender plugin → cannot work without transport plugin → conflates transport and sending concerns ``` There are a few issues with this: - HttpPlugin created NEW Client instances on every send() call. So there's really no benefit of this logic being in the "httpclient" plugin. - Transport plugins (HttpPlugin) were forced to implement send/createStream. This makes it more cumbersome to build your own HttpPlugin with your own servier. - Users couldn't "bring their own server" without implementing ISender - ActivityContext was tightly coupled to plugin architecture. ("Sender" was coupled with an activity, without any necessary benefits.) ## New Architecture ``` HttpPlugin (transport) → only handles HTTP server/routing/auth → emits CoreActivity (minimal protocol knowledge) → just passes body payload to app ActivitySender (NEW) → dedicated class for sending activities → receives injected, reusable Client → handles all send/stream logic → private to App class ActivityContext → uses ActivitySender now, which is not a plugin ``` In this PR, I am mainly decoupling responsibilities of HttpPlugin from being BOTH a listener AND a sender, to being just a listener. The sender bit is now separated to a different `ActivitySender` class. Other than better code organization, the main thing this lets us do is **not require the app to run to be able to send proactive messages**. This is a huge plus point because now the App can be used in scenarios where it doesn't necessarily need to _listen_ to incoming messages (like agentic notifications!) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary - **Replace `HttpPlugin` with `HttpServer` + `HttpServerAdapter` pattern** — follows the [TS PR #433](AzureAD/microsoft-authentication-library-for-js#433) approach - `HttpServer` is no longer a plugin — it's owned directly by `App` - Introduces `HttpServerAdapter` protocol with `FastAPIAdapter` as the default implementation - Plugins inject `HttpServer` via DI and access the framework via `server.adapter` - Framework-agnostic handler pattern: `async (HttpRequest) -> HttpResponse` - Rewrites `remote_function_jwt_middleware` to be framework-agnostic - Adds `examples/http-adapters/` with Starlette adapter and non-managed FastAPI examples Stacked on #249 ## Test plan - [x] Update unit tests - [x] Run `poe test` — all tests pass - [x] Run AI sample end-to-end - [x] Run MCP sample end-to-end - [x] Run Echo Bot sample end-to-end - [x] Run Dialog sample end-to-end - [x] Run Tab sample end-to-end - [x] Run BotBuilder sample end-to-end 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…sages as preview (#306) - `ExperimentWarning` is a subclass to `FutureWarning` so users supress preview API warnings if desired. - @experimental("ExperimentalTeamsReactions") decorator - emits warnings when applied to a class or function - Mark reactions and targeted messages as preview Note that suppression is not granular - while C# differentiates between different diagnostics, the ignore below will suppres all preview warnings. To suppress the warnings: ```python import warnings from microsoft_teams.common.experimental import ExperimentalWarning warnings.filterwarnings("ignore", category=ExperimentalWarning) ``` --------- Co-authored-by: Corina Gum <>
## Summary - Make `HttpServer.handle_request` public so plugins can route through SDK-level JWT validation - Change DI from `HttpServerAdapter` to `HttpServer` — plugins now inject `HttpServer` and access the adapter via `.adapter` - BotBuilderPlugin runs CloudAdapter auth first, then calls `http_server.handle_request()` for SDK auth + Teams pipeline (previously bypassed `TokenValidator` entirely) - Remove pass-through methods (`register_route`, `serve_static`, `start`, `stop`) from `HttpServer` — callers go through `server.adapter` directly ## Test plan - [x] `uv run pyright` — no new type errors - [x] `poe test` — all apps, botbuilder, mcpplugin tests pass (153 tests) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Previously, we had a custom logger available for customers. However, this didn't integrate very well with the general industry - other libraries and frameworks use python's `logging` library (e.g., fastapi, boto3, etc), and most developers are familiar with it. In addition, using the standard library is better for reliability, and requires less maintenance. - updated to use module level logging throughout the packages (removed from constructors, dependency injections) - removed the `ConsoleLogger`, `LoggerDependencyOption`, and `EventEmitterOptions` (it only has a logger property) - kept the `ConsoleFormatter` and `ConsoleFilter` as an option for developers to use - added the `NullHandler` so that no errors/warnings will show up when logger has not yet been configured (added to every package init file) - updated common/README to explain how to setup and customize the logger - removed mock loggers from tests - regenerated the handlers now that logger is no longer a property example w/ standard logger, using our custom formatter: <img width="1165" height="300" alt="image" src="https://github.com/user-attachments/assets/5cf51fc7-ea0c-4c36-8cc6-b93b040f31ed" /> Sharing notes/observations. I looked at the most popular python libraries, as well as the most popular multi-package sdks. **Pattern 1 - Single top-level logger (FastAPI, httpx, stripe)** Simple, all log output is under one namespace, but all of the output is in one undifferentiated stream. No granularity. **Pattern 2 - Per module logger (OpenAI, Anthropic, urllib4, botocore, azure sdks, google cloud sdks)** Fine-grained, names expose the internal implementation details **Pattern 3 - Central log.py file, with named subsystems (aiohttp)** Stable, intuitive because users filter by what the system is doing since all logger definitions live in one spot. Very much overkill, requires more coordination, rare design if subsystems don't need such independent filtering. If users don't want to see any logs, thats what `NullHandler` is for - logs are silent and python warnings are suppressed. **When users want to see all the logs:** logging.getLogger("microsoft_teams").setLevel(logging.DEBUG) **When users want to narrow it down:** logging.getLogger("microsoft_teams.ai").setLevel(logging.DEBUG) --------- Co-authored-by: lilydu <lilydu+odspmdb@microsoft.com>
closes: #64 - added code and branch coverage tracking via pytest-cov - added to CI, threshold set to 74% with current stat, should raise to 80% once more tests are added ## Usage ```bash # Run tests with coverage report uv run poe test-cov # Generate XML coverage for CI uv run poe test-cov-xml # Open HTML coverage report open htmlcov/index.html OR start htmlcov/index.html ``` current coverage: 74.33% ## Next Steps 1. add tests for untested packages (a2aprotocol, devtools) 2. improve coverage for minimally-tested packages (ai, botbuilder, graph, mcpplugin) --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: lilydu <lilydu+odspmdb@microsoft.com> Co-authored-by: Lily Du <lilyyduu@gmail.com> Co-authored-by: heyitsaamir <ajawaid191@gmail.com>
Moved IsTargeted from Activity to Account Updated routing logic to read from Recipient.IsTargeted instead of Activity.IsTargeted
Fixes a bug where API client URLs could contain double slashes if the `service_url` parameter had a trailing slash (e.g., `https://service.url/` would produce `https://service.url//v3/conversations/...`). ## Changes Made - **URL normalization**: Added `.rstrip("/")` when assigning `service_url` in the `__init__` of all API clients: `ConversationActivityClient`, `ConversationClient`, `ConversationMemberClient`, `MeetingClient`, `TeamClient`, `ReactionClient`, and `ApiClient`. - **Sub-client propagation**: Updated `ConversationClient` and `ApiClient` to pass the already-normalized `self.service_url` to sub-client constructors, ensuring consistency throughout the client hierarchy. - **Tests**: Added tests to `test_conversation_client.py`, `test_reaction_client.py`, `test_team_client.py`, and `test_meeting_client.py` to verify that trailing slashes are stripped and no double slashes appear in constructed URLs. ## Testing - ✅ All 128 existing API unit tests pass - ✅ New tests verify trailing slash stripping across all affected clients - ✅ Ruff linting and formatting checks pass - ✅ CodeQL security scan found no issues <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: heyitsaamir <48929123+heyitsaamir@users.noreply.github.com>
## Summary - Upgrade transitive dependencies to resolve 8 of 9 known vulnerabilities found via `pip-audit` - Raise minimum version floors for `pyjwt` and `fastmcp` to prevent vulnerable versions from resolving on fresh installs - Fix stale test from #318 that expected removed recipient-inference behavior ## Vulnerabilities Fixed | Package | Before | After | CVE | |---------|--------|-------|-----| | authlib | 1.6.6 | 1.6.9 | CVE-2026-28802 (JWT `alg:none` bypass) | | cryptography | 46.0.3 | 46.0.5 | CVE-2026-26007 (EC subgroup validation) | | fastmcp | 2.14.0 | 3.1.1 | CVE-2025-69196 | | pyjwt | 2.10.1 | 2.12.1 | CVE-2026-32597 (`crit` header bypass) | | pyasn1 | 0.6.2 | 0.6.3 | CVE-2026-30922 (recursion bomb DoS) | | starlette | 0.49.1 | 1.0.0 | CVE-2025-43859 (HTTP request smuggling) | | fastapi | 0.128.0 | 0.135.2 | (pulled by starlette) | | diskcache | 5.6.3 | removed | CVE-2025-69872 (no longer needed with fastmcp 3.x) | **Unfixable:** jsonpickle 1.4.2 (CVE-2020-22083) — pinned by `botbuilder-core` to `>=1.2,<1.5`. ## Floor Constraint Changes - `pyjwt[crypto]>=2.12.0` in api, apps, graph (was `>=2.10.0`) - `fastmcp>=2.14.2` in mcpplugin (was `>=0.5.0`) ## Test plan - [x] `poe test` — 546 passed, 0 failed - [x] E2E tested echo, mcp-server, mcp-client, botbuilder examples against live Teams 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary - Currently `/api/messages` is hardcoded as the messaging endpoint path. This might not be always what a developer wants. - Adds `messaging_endpoint` option to `AppOptions` (defaults to `/api/messages`) - `App` is the source of truth for the default; `HttpServer` requires it explicitly - `BotBuilderPlugin` reads the path from `http_server.messaging_endpoint` instead of hardcoding Port of microsoft/teams.ts#483 ## Test plan - [x] Existing `test_http_server.py` tests pass - [x] New test for default messaging endpoint value - [x] New test for custom messaging endpoint registration - [x] Manual test with a custom endpoint path 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merge latest changes from
mainintoalpha/v2.0.0to produce the next alpha release.What's included
Breaking changes
HttpPluginwithHttpServer+HttpServerAdapterarchitecture (Replace HttpPlugin with HttpServer + HttpServerAdapter #310, Simply HttpPlugin to only focus on server-concepts #249)IsTargetedproperty fromActivitytoAccount(Move IsTargeted property from Activity to Account #318)logginglibrary (remove custom logger, use standard logging library #270)Features
ExperimentalWarningclass; mark reactions and targeted messages as preview (Add ExperimentalWarning class and indicate reactions and targeted messages as preview #306)pytest-covfor code & branch coverage reporting (feat: add pytest-cov for code & branch reporting #244)Bug fixes
HttpServer.handle_request(Route BotBuilder auth through HttpServer.handle_request #313)Other
CLAUDE.mdfor development guidance (Add claude.md file #309)Next steps
alpha/v2.0.0🤖 Generated with Claude Code